import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // home: ScrollControllerTestRoute(),
      home: const MyHomePage(
        title: 'demo',
      ),
    );
  }
}

// Flutter中可以使用Listener来监听原始触摸事件
// Listener({
//   Key key,
//   this.onPointerDown, //手指按下回调
//   this.onPointerMove, //手指移动回调
//   this.onPointerUp,//手指抬起回调
//   this.onPointerCancel,//触摸事件取消回调
//   this.behavior = HitTestBehavior.deferToChild, //先忽略此参数，后面小节会专门介绍
//   Widget child
// })

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Column(
        children: [
          PointerMoveIndicator(),
          Listener(
            child: AbsorbPointer(
              child: Listener(
                child: Container(
                  color: Colors.red,
                  width: 200.0,
                  height: 100.0,
                ),
                onPointerDown: (event) => print("in"),
              ),
            ),
            onPointerDown: (event) => print("up"),
          )
        ],
      ),
    );
  }
}

class PointerMoveIndicator extends StatefulWidget {
  PointerMoveIndicator({Key? key}) : super(key: key);

  @override
  State<PointerMoveIndicator> createState() => _PointerMoveIndicatorState();
}

class _PointerMoveIndicatorState extends State<PointerMoveIndicator> {
  PointerEvent? _event;

  @override
  Widget build(BuildContext context) {
    return Listener(
      child: Container(
        alignment: Alignment.center,
        color: Colors.blue,
        width: 300.0,
        height: 150.0,
        child: Text(
          '${_event?.localPosition ?? ''}, ${_event?.delta ?? ''}, ${_event?.localPosition.dx ?? ''}, ${_event?.localPosition.dy ?? ''}',
          style: TextStyle(color: Colors.white),
        ),
      ),
      onPointerDown: (PointerDownEvent event) => setState(() => _event = event),
      onPointerMove: (PointerMoveEvent event) => setState(() => _event = event),
      onPointerUp: (PointerUpEvent event) => setState(() => _event = event),
    );
  }
}

// 当触发指针事件时，参数 PointerDownEvent、 PointerMoveEvent、 PointerUpEvent 都是PointerEvent的子类，PointerEvent类中包括当前指针的一些信息，注意 Pointer，即“指针”， 指事件的触发者，可以是鼠标、触摸板、手指

// position：它是指针相对于当对于全局坐标的偏移。
// localPosition: 它是指针相对于当对于本身布局坐标的偏移。
// delta：两次指针移动事件（PointerMoveEvent）的距离。
// pressure：按压力度，如果手机屏幕支持压力传感器(如iPhone的3D Touch)，此属性会更有意义，如果手机不支持，则始终为1。
// orientation：指针移动方向，是一个角度值。

// 假如我们不想让某个子树响应PointerEvent的话，我们可以使用IgnorePointer和AbsorbPointer，这两个组件都能阻止子树接收指针事件，不同之处在于AbsorbPointer本身会参与命中测试，而IgnorePointer本身不会参与，这就意味着AbsorbPointer本身是可以接收指针事件的(但其子树不行)，而IgnorePointer不可以。

// 点击Container时，由于它在AbsorbPointer的子树上，所以不会响应指针事件，所以日志不会输出"in"，但AbsorbPointer本身是可以接收指针事件的，所以会输出"up"。如果将AbsorbPointer换成IgnorePointer，那么两个都不会输出。

// Listener(
//   child: AbsorbPointer(
//     child: Listener(
//       child: Container(
//         color: Colors.red,
//         width: 200.0,
//         height: 100.0,
//       ),
//       onPointerDown: (event)=>print("in"),
//     ),
//   ),
//   onPointerDown: (event)=>print("up"),
// )